/*
 * SIT_Slider.c : control that enable to choose among a range of discreet values
 *
 * Written by T.Pierron, Dec 02, 2008.
 */

#include "SIT_P.h"
#include <stdio.h>

	TagList SliderClass[] = {
		{ SIT_SuperClass,  NULL,          ___, SIT_INT,  (ULONG) WidgetClass },
		{ SIT_MinValue,    "minValue",    _SG, SIT_INT,  OFFSET(SIT_Slider, tb_MinValue) },
		{ SIT_MaxValue,    "maxValue",    _SG, SIT_INT,  OFFSET(SIT_Slider, tb_MaxValue) },
		{ SIT_PageSize,    "pageSize",    _SG, SIT_INT,  OFFSET(SIT_Slider, tb_PageSize) },
		{ SIT_SliderPos,   "sliderPos",   _SG, SIT_INT,  OFFSET(SIT_Slider, tb_SliderPos) },
		{ SIT_TickFreq,    "tickFreq",    _SG, SIT_INT,  OFFSET(SIT_Slider, tb_TickFreq) },
		{ SIT_TickStyle,   "tickStyle",   C__, SIT_INT,  OFFSET(SIT_Slider, tb_Styles) },
		{ SIT_HorizScroll, "horizScroll", C__, SIT_BOOL, OFFSET(SIT_Slider, tb_IsHoriz) },
		{ SIT_ThumbWidth,  "thumbWidth",  _SG, SIT_INT,  OFFSET(SIT_Slider, tb_ThumbWidth) },
		{ SIT_BuddyEdit,   "buddyEdit",   _SG, SIT_CTRL, OFFSET(SIT_Slider, tb_Buddy) },
		{ SIT_TagEnd }
	};


/* Group modifications of widget into one call to avoid flicker */
static int SIT_ApplySliderStyles(SIT_Widget w, APTR call_data, APTR user_data)
{
	SIT_Slider s = (SIT_Slider) w;

	/* Page size - do not imply any visual changes */
	if (s->tb_Mask & SIF_PAGE)
	{
		SendMessage(w->sw_Handle, TBM_SETPAGESIZE, FALSE, s->tb_PageSize);
		s->tb_Mask &= ~ SIF_PAGE;
	}

	if (s->tb_Mask & SIF_RANGE)
	{
		SendMessage(w->sw_Handle, TBM_SETRANGEMIN, FALSE, s->tb_MinValue);
		SendMessage(w->sw_Handle, TBM_SETRANGEMAX, s->tb_Mask == SIF_RANGE, s->tb_MaxValue);
		s->tb_Mask &= ~ SIF_RANGE;
	}

	if (s->tb_Mask & SIF_POS)
	{
		SendMessage(w->sw_Handle, TBM_SETPOS, s->tb_Mask == SIF_POS, s->tb_SliderPos);
		if (s->tb_Buddy)
		{
			WCHAR num[10];
			wsprintf(num, L"%d", s->tb_SliderPos);
			SetWindowText(s->tb_Buddy->sw_Handle, num);
		}
		s->tb_Mask &= ~ SIF_POS;
	}

	if (s->tb_Mask & SIF_TRACKPOS)
	{
		SendMessage(w->sw_Handle, TBM_SETTICFREQ, s->tb_TickFreq, 0);
		s->tb_Mask &= ~ SIF_TRACKPOS;
	}
	w->sw_PostProcess = NULL;
	return 0;
}

static int SIT_SetSliderValues(SIT_Widget w, APTR call_data, APTR user_data)
{
	TagList *     tag   = call_data;
	SIT_Variant * value = user_data;
	SIT_Slider    s     = (SIT_Slider) w;
	int           isSet = 0;

	switch (tag->tl_TagID) {
	case SIT_MinValue:    s->tb_MinValue  = value->integer; isSet = SIF_RANGE; break;
	case SIT_MaxValue:    s->tb_MaxValue  = value->integer; isSet = SIF_RANGE; break;
	case SIT_PageSize:    s->tb_PageSize  = value->integer; isSet = SIF_PAGE;  break;
	case SIT_SliderPos:   s->tb_SliderPos = value->integer; isSet = SIF_POS;   break;
	case SIT_TickFreq:    s->tb_TickFreq  = value->integer; isSet = SIF_TRACKPOS; break;
	case SIT_TickStyle:   s->tb_Styles    = value->integer; break;
	case SIT_HorizScroll: s->tb_IsHoriz   = value->integer; break;
	case SIT_ThumbWidth:  SendMessage(w->sw_Handle, TBM_SETTHUMBLENGTH, s->tb_ThumbWidth = value->integer, 0); break;
	case SIT_BuddyEdit:
		w = s->tb_Buddy = value->pointer;
		if (w->sw_Type == SIT_EDITBOX) /* It will trigger event back to TB */
			((SIT_EditBox)w)->se_BuddyTB = &s->super;
		break;
	default: return SIT_SetWidgetValue(w, call_data, user_data); // super class
	}

	if (isSet)
	{
		s->tb_Mask |= isSet;
		w->sw_PostProcess = SIT_ApplySliderStyles;
	}
	return 0;
}

/* Set minimal width/height */
static int SIT_MeasureSlider(SIT_Widget w, APTR call_data, APTR user_data)
{
	SIT_Slider s   = (SIT_Slider) w;
	SIZE *     ret = call_data;
	int        min = 24;

	if ((s->tb_Styles & SITV_TicksNone) == 0)
		min = (s->tb_Styles == (SITV_TicksTop | SITV_TicksBottom) ? 40 : 33);

	if (s->tb_IsHoriz) ret->cy = min;
	else               ret->cx = min;

	return 0;
}

/* Control creation */
BOOL SIT_CreateSlider(SIT_Widget w, va_list args)
{
	SIT_Slider s = (SIT_Slider) w;
	HWND       hwnd;
	int        style = WS_CHILD | TBS_AUTOTICKS | TBS_FIXEDLENGTH;

	/* Subclass SetValues */
	w->sw_SetValue = SIT_SetSliderValues;
	w->sw_OptimalWidth = SIT_MeasureSlider;

	/* Default values */
	s->tb_TickFreq = 1;
	s->tb_IsHoriz  = True;
	s->tb_MaxValue = 100;
	SIT_ParseTags(w, args, w->sw_Class = SliderClass);

	switch (s->tb_Styles) {
	case 1: style |= TBS_NOTICKS; break;
	case 2: style |= TBS_TOP; break;
	case 3: style |= TBS_TOP|TBS_NOTICKS; break;
	case 4: style |= TBS_BOTTOM; break;
	case 5: style |= TBS_BOTTOM|TBS_NOTICKS; break;
	case 6: style |= TBS_BOTH; break;
	case 7: style |= TBS_BOTH|TBS_NOTICKS;
	}
	if (IsVisible(w)) style |= WS_VISIBLE;
	if (HAS_TAB(w))   style |= WS_TABSTOP;

	/* Create Win32 control, pos and dim will be set later */
	hwnd = w->sw_Handle = CreateWindow(TRACKBAR_CLASS, w->sw_Name,
		style | (s->tb_IsHoriz ? TBS_HORZ : TBS_VERT),
		0, 0, 10, 10, SIT_GetContainer(w), (HMENU) MAKE_ID(w), instance, NULL);

	if (hwnd == NULL) return FALSE;
	SIT_SetDefaultFont(w);

	/* Get default values of control if not set by user */
	if ((s->tb_Mask & SIF_PAGE) == 0)
		s->tb_PageSize = SendMessage(w->sw_Handle, TBM_GETPAGESIZE, 0, 0);

	if (s->tb_ThumbWidth > 0)
		SendMessage(w->sw_Handle, TBM_SETTHUMBLENGTH, s->tb_ThumbWidth, 0);
	if (w->sw_PostProcess)
		w->sw_PostProcess(w, NULL, NULL);

	SetProp(hwnd, sit_class, (HANDLE) w);

	return TRUE;
}
